package cloud.xiangyixiang.www.spring.boot.java.basics.controller;

import cloud.xiangyixiang.www.spring.boot.java.basics.annotations.*;
import cloud.xiangyixiang.www.spring.boot.java.basics.enums.BirdNestEnum;
import cloud.xiangyixiang.www.spring.boot.java.basics.utils.AttributeAnnotation;
import cloud.xiangyixiang.www.spring.boot.java.basics.utils.Bird;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * <p>
 * JAVA Annotation 注解
 * </p>
 *
 * @author zhixinglu
 * @date 2023/9/6 10:56
 */
@TestAnnotation
public class AnnotationController {

    public static void main(String[] args) {
        description();

        test1();

        test2();

        test3();

        test4();

        test5();

        test6();

        test7();

        test8();
    }

    /**
     * 介绍详情
     */
    public static void description(){
        System.out.println("介绍详情：==========================");

        System.out.println("Java注解用于为Java代码提供元数据。");

        System.out.println("元数据是指用来描述数据的数据，通俗一点，就是描述代码间关系，或者代码与其它资源（例如数据库表）之间内在联系的数据。在一些技术框架中，如Struts、hibernate就不知不觉用到了元数据。对于Struts来说，元数据指的是struts-config.xml；对hibernate来说就是hbm文件。以上阐述的几种元数据都是基于xml文件的或者其他形式的单独配置文件。这样表示有些不便之处。1、与被描述的文件分离，不利于一致性的维护；2、所有这样的文件都是ASCII文件，没有显式的类型支持。基于元数据的广泛使用，JDK5.0引入了Annotation的概念来描述元数据。在Java中，元数据以标签的形式存在于Java代码中，元数据标签的存在并不影响程序代码的编译和执行。简而言之，言而总之，注解就是标签的意思。");

        System.out.println("总结：");
        System.out.println("    1.注解就是标签，注解为了解释代码");
        System.out.println("    2.注解的基本语法@interface");
        System.out.println("    3.注解的元注解");
        System.out.println("    4.注解的属性");
        System.out.println("    5.注解主要给编译器及工具类型的软件用的");
        System.out.println("    6.注解的提取要借助于Java的反射技术，反射比较慢，所以注解使用时也需要谨慎计较时间成本");

        System.out.println();
    }

    private static void test1(){
        if(Man.class.isAnnotationPresent(Persons.class)) {
            Persons p2 = Man.class.getAnnotation(Persons.class);
            for(Person t : p2.value()){
                System.out.println(t.role());
            }
        }
        System.out.println();
    }

    private static void test2(){
        Annotation[] annotations = Man.class.getAnnotations();
        System.out.println(annotations.length);
        Persons p1 = (Persons) annotations[0];
        for(Person t : p1.value()){
            System.out.println(t.role());
        }
        System.out.println();
    }

    /**
     * 不推荐使用方法注解 @Deprecated
     */
    private static void test3(){
        System.out.println("标识不推荐使用注解 @Deprecated： =============");
        Hero hero = new Hero();
        hero.addItems("刘亦菲");
        hero.say();
        hero.speak();
        System.out.println();
    }

    /**
     * 阻止警告注解 @SuppressWarnings
     */
    @SuppressWarnings("deprecation")
    private static void test4(){
        System.out.println("阻止警告注解 @SuppressWarnings： =============");
        Hero hero = new Hero();
        hero.addItems("刘亦菲");
        hero.say();
        hero.speak();
        System.out.println();
    }

    /**
     * 参数安全类型注解  @SafeVarargs
     */
    private static void test5(){
        System.out.println("参数安全类型注解 @SafeVarargs: ==============");

        SafeVarargsAnnotation.loopPrintInfo("A","B","C");

        System.out.println();

    }

    /**
     * 反射获取注解
     */
    private static void test6(){
        System.out.println("注解通过反射获取: =================");

        boolean hasAnnotation = TestAnnotation.class.isAnnotationPresent(TestAnnotation.class);
        if(hasAnnotation){
            TestAnnotation testAnnotation = TestAnnotation.class.getAnnotation(TestAnnotation.class);
            System.out.println("id:"+testAnnotation.id());
            System.out.println("msg:"+testAnnotation.msg());
        }

        System.out.println();

    }

    /**
     * 属性上添加注解
     */
    private static void test7(){
        System.out.println("属性上添加注解: =====================");
        boolean hasAnnotation = AttributeAnnotation.class.isAnnotationPresent(TestAnnotation.class);
        if ( hasAnnotation ) {
            TestAnnotation testAnnotation = AttributeAnnotation.class.getAnnotation(TestAnnotation.class);
            //获取类的注解
            System.out.println("id:" + testAnnotation.id());
            System.out.println("msg:" + testAnnotation.msg());
        }
        try {
            Field a = AttributeAnnotation.class.getDeclaredField("a");
            a.setAccessible(true);
            // 获取一个成员变量上的注解
            Check check = a.getAnnotation(Check.class);
            if ( check != null ) {
                System.out.println("check value:"+check.value());
            }
            Method testMethod = AttributeAnnotation.class.getDeclaredMethod("testMethod");
            if ( testMethod != null ) {
                // 获取方法中的注解
                Annotation[] ans = testMethod.getAnnotations();
                for( int i = 0;i < ans.length;i++) {
                    System.out.println("method testMethod annotation:"+ans[i].annotationType().getSimpleName());
                }
            }
        } catch (NoSuchFieldException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            System.out.println(e.getMessage());
        } catch (SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            System.out.println(e.getMessage());
        } catch (NoSuchMethodException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            System.out.println(e.getMessage());
        }
        System.out.println();
    }

    private static void test8(){
        System.out.println("子类继承父类时，注解会自动集成 @Inherited：============");
        Bird bird = BirdNestEnum.Sparrow.reproduce();
        Desc.Color color = bird.getColor();
        System.out.println("Bird's color is : " + color);
    }

}
